import { _decorator, ERaycast2DType, PhysicsSystem2D, RigidBody2D, tween, Vec2, Vec3 } from 'cc';
import { DIRECTION_ENUM, PARAME_NAME_ENUM, LEAPING_NAME_ENUM, GAME_MODE_ENUM } from '../../Enums';
import DataManager from '../Runtime/DataManager';
import { getRandomNumber, roundToNearestInteger } from '../utils';
import { BaseEnemy } from './BaseEnemy';
const { ccclass } = _decorator;
// 会飞的怪物
@ccclass('LeapingEnemy')
export class LeapingEnemy extends BaseEnemy {
    speed: number = 3
    positionY: number = 20
    positionX: number = 0
    randomNumber: number = 0
    dizzy_direction: string = ""

    init(list) {
        this.randomNumber = getRandomNumber(0, 1)
        super.initialization(
            "LeapingEnemy",
            this.positionX,
            this.positionY,
            this.positionX + 4,
            this.positionY,
            LEAPING_NAME_ENUM,
            list
        )
        setTimeout(res => {
            this.initialize = true
            this.getNextLineList()
        }, 300)
    }
    getNextLineList() {
        let { width, position, player } = DataManager.Instance
        let targetX, targetY
        // 如果有一个角色,就追这一个角色
        // 如果有两个角色,就随机追一个
        if (player.length == 1) {
            targetX = player[0].node.getPosition().x
            targetY = player[0].node.getPosition().y
        } else if (player.length == 2) {
            targetX = player[this.randomNumber].node.getPosition().x
            targetY = player[this.randomNumber].node.getPosition().y
        } else {
            return
        }
        let { x, y } = this.node.getPosition()
        let multipleX = roundToNearestInteger(parseInt(x - targetX + '') / width)
        let multipleY = roundToNearestInteger(parseInt(y - targetY + '') / position)
        let lineList = []
        let randomNumber = getRandomNumber(1, 2)
        // 如果不在一条直线上
        if (multipleX != 0 && multipleY != 0) {
            if (randomNumber == 1) {
                lineList = this.setLineList(1, multipleX)
            } else {
                lineList = this.setLineList(0, multipleY)
            }
        }
        if (multipleX != 0 && multipleY == 0) {
            lineList = this.setLineList(1, multipleX)
        }
        if (multipleX == 0 && multipleY != 0) {
            lineList = this.setLineList(0, multipleY)
        }
        this.lineList = lineList
        if (this.lineList.length != 0) {
            if (this.status != this.lineList[0].status) {
                this.setStatus(this.lineList[0].status)
            }
            this.getDirectionPhysics(this.lineList[0].direction)
        }
    }
    // 获取怪物的状态信息
    getSendData() {
        if (this.node && this.node.isValid) {
            let { targetX, targetY, direction, state } = this.playManager
            return {
                name: this.node.name,
                x: Math.round(this.node.getPosition().x / this.speed) * this.speed,// 位置
                y: Math.round(this.node.getPosition().y / this.speed) * this.speed,
                direction,
                state,
                lineList:this.lineList,
                fly: false,
                avoid: false,
                running: false,
                status: this.status,
                dizzy: this.dizzy,
                speed: this.speed,
                dizzy_direction: this.dizzy_direction,
                callback: this.callback,
                callback_A: this.callback_A,
                callbackAvoid: this.callbackAvoid,
                targetX,
                targetY
            }
        }
    }
    // 强制设置角色的状态
    setSendData(data) {
        if (!data) return
        if (this.node && this.node.isValid) {
            if (!data?.x || !data?.y) return
            this.node.setPosition(data.x, data.y)
            this.playManager.targetX = data.targetX
            this.playManager.targetY = data.targetY
            this.playManager.direction = data.direction
            this.dizzy = data.dizzy
            this.lineList=data.lineList
            this.dizzy_direction = data.dizzy_direction
            this.status = data.status
            this.speed = data.speed
            clearTimeout(this.callback)
            clearTimeout(this.callback_A)
            if (this.playManager.state != data.state) {
                this.playManager.state = data.state
            }
        }
    }
    setLineList(type, multiple) {
        let { width, position } = DataManager.Instance
        let { x, y } = this.node.getPosition()
        let numberX = x, numberY = y
        if (type == 0) {
            let direction = DIRECTION_ENUM.BOTTOM
            let status = "bottom"
            if (multiple > 0) {
                numberY = numberY - position
            }
            if (multiple < 0) {
                status = "top"
                direction = DIRECTION_ENUM.TOP
                numberY = numberY + position
            }
            return [{
                targetX: numberX,
                targetY: numberY,
                direction,
                status
            }]
        } else {
            let direction = DIRECTION_ENUM.LEFT
            let status = "left"
            if (multiple > 0) {
                numberX = numberX - width
            }
            if (multiple < 0) {
                direction = DIRECTION_ENUM.RIGHT
                status = "right"
                numberX = numberX + width
            }
            return [{
                targetX: numberX,
                targetY: numberY,
                direction,
                status
            }]
        }
    }
    // 判断前方是否有障碍物
    getDirectionPhysics(direction: DIRECTION_ENUM) {
        let start = new Vec2(this.node.getWorldPosition().x, this.node.getWorldPosition().y)
        let endX = this.node.getWorldPosition().x
        let endY = this.node.getWorldPosition().y
        if (direction == DIRECTION_ENUM.TOP) {
            endY = endY + 120
        } else if (direction == DIRECTION_ENUM.BOTTOM) {
            endY = endY - 120
        } else if (direction == DIRECTION_ENUM.LEFT) {
            endX = endX - 120
        } else if (direction == DIRECTION_ENUM.RIGHT) {
            endX = endX + 120
        }
        let filterName = ['enemy', 'sensor', 'children_lurker', 'slide', 'role']
        const data2 = PhysicsSystem2D.instance.testPoint(start)
        let list2 = data2.filter((item => !filterName.find(item1 => item.node.name.includes(item1)))) //有值代表身下有道具
        const data = PhysicsSystem2D.instance.raycast(start, new Vec2(endX, endY), ERaycast2DType.All)
        let list = data.filter((item => !filterName.find(item1 => item.collider.node.name.includes(item1))))
        // 如果是起飞状态,并且前面还有障碍物,就降落到空气上
        if (list.length != 0 || list2.length != 0) {
            this.setFlyStart()
            this.fly = true
            this.node.children[0].getChildByName("shadow").active = false
            this.node.setSiblingIndex(999)
        } else {
            if (this.playManager.state.includes("fly")) {
                setTimeout(() => {
                    this.setFlyEnd()
                }, 300)
            } else {
                this.fly = false
                this.node.children[0].getChildByName("shadow").active = true
                this.speed = 3
            }
        }
    }
    // 开始起飞
    setFlyStart() {
        let start_ing = LEAPING_NAME_ENUM.LEFTFLYING
        let jump_y = 60
        this.speed = 1.5
        if (this.playManager.direction == DIRECTION_ENUM.LEFT) {
            this.playManager.state = LEAPING_NAME_ENUM.LEFTFLY
        } else if (this.playManager.direction == DIRECTION_ENUM.RIGHT) {
            start_ing = LEAPING_NAME_ENUM.RIGHTFLYING
            this.playManager.state = LEAPING_NAME_ENUM.RIGHTFLY
        } else if (this.playManager.direction == DIRECTION_ENUM.TOP) {
            start_ing = LEAPING_NAME_ENUM.TOPFLYING
            this.playManager.state = LEAPING_NAME_ENUM.TOPFLY
            jump_y = 0
        } else if (this.playManager.direction == DIRECTION_ENUM.BOTTOM) {
            start_ing = LEAPING_NAME_ENUM.BOTTOMFLYING
            this.playManager.state = LEAPING_NAME_ENUM.BOTTOMFLY
            jump_y = 0
        }
        if (this.fly) {
            this.playManager.state = start_ing
        } else {
            tween(this.userNode)
                .to(.5, { position: new Vec3(this.positionX, this.positionY + jump_y, 0) })
                .call(() => {
                    this.playManager.state = start_ing
                })
                .start()
        }
    }
    // 起飞结束
    setFlyEnd() {
        let end_state = LEAPING_NAME_ENUM.LEFT
        if (this.playManager.direction == DIRECTION_ENUM.LEFT) {
            this.playManager.state = LEAPING_NAME_ENUM.LEFTFLYEND
        } else if (this.playManager.direction == DIRECTION_ENUM.RIGHT) {
            this.playManager.state = LEAPING_NAME_ENUM.RIGHTFLYEND
            end_state = LEAPING_NAME_ENUM.RIGHT
        } else if (this.playManager.direction == DIRECTION_ENUM.TOP) {
            this.playManager.state = LEAPING_NAME_ENUM.TOPFLYEND
            end_state = LEAPING_NAME_ENUM.TOP
        } else if (this.playManager.direction == DIRECTION_ENUM.BOTTOM) {
            this.playManager.state = LEAPING_NAME_ENUM.BOTTOMFLYEND
            end_state = LEAPING_NAME_ENUM.BOTTOM
        }
        if (this.playManager.direction == DIRECTION_ENUM.BOTTOM || this.playManager.direction == DIRECTION_ENUM.TOP) {
            this.fly = false
            this.node.children[0].getChildByName("shadow").active = true
        }
        tween(this.userNode)
            .to(.5, { position: new Vec3(this.positionX, this.positionY, 0) })
            .call(() => {
                if (this.playManager.direction == DIRECTION_ENUM.LEFT || this.playManager.direction == DIRECTION_ENUM.RIGHT) {
                    this.fly = false
                    this.node.children[0].getChildByName("shadow").active = true
                }
                this.speed = 3
                this.playManager.state = end_state
            })
            .start()
    }

    update() {
        if (DataManager.Instance.gameMode == GAME_MODE_ENUM.ONLINE) {
            if (!DataManager.Instance.game_ready) return
            if (DataManager.Instance.ping_time >= 460) {
                let rb = this.node.getComponent(RigidBody2D)
                rb!.linearVelocity = new Vec2(0, 0)
                return
            }
        }
        if (this.dizzy) {
            this.dizzy_update()
        } else {
            this.enemy_update()
        }
    }
    enemy_update() {
        if (this.dizzy) return
        let rb = this.node.getComponent(RigidBody2D)
        let speed = this.speed
        if (this.dizzy) {
            speed = 5
        }
        let lv = rb!.linearVelocity;
        let { x, y } = this.node.getPosition()
        y = Math.round(y / this.speed) * this.speed
        x = Math.round(x / this.speed) * this.speed
        if (this.status == "left") {
            lv.x = -speed;
            lv = new Vec2(lv.x, 0);
        } else if (this.status == "right") {
            lv.x = speed;
            lv = new Vec2(lv.x, 0);
        } else if (this.status == "top") {
            lv.y = +speed;
            lv = new Vec2(0, lv.y);
        } else if (this.status == "bottom") {
            lv.y = -speed;
            lv = new Vec2(0, lv.y);
        } else {
            lv = new Vec2(0, 0);
        }
        if (this.lineList.length > 0) {
            let { targetX, targetY, direction } = this.lineList[0]
            if (direction == DIRECTION_ENUM.LEFT || direction == DIRECTION_ENUM.RIGHT) {
                if (targetX != 0) {
                    if (x > parseInt(targetX + '')) {
                        lv.x = -speed;
                        lv = new Vec2(lv.x, 0);
                        this.playManager.disabled = true
                    } else if (x < parseInt(targetX + '')) {
                        lv.x = +speed;
                        lv = new Vec2(lv.x, 0);
                        this.playManager.disabled = true
                    } else {
                        this.node.setPosition(targetX, y)
                        this.playManager.targetX = 0
                        this.playManager.disabled = false
                        lv = new Vec2(0, 0);
                        this.getNextLineList()
                    }
                }
            }
            if (direction == DIRECTION_ENUM.TOP || direction == DIRECTION_ENUM.BOTTOM) {
                if (targetY != 0) {
                    if (y < parseInt(targetY + '')) {
                        lv.y = +speed;
                        lv = new Vec2(0, lv.y);
                        this.playManager.disabled = true
                    } else if (y > parseInt(targetY + '')) {
                        lv.y = -speed;
                        lv = new Vec2(0, lv.y);
                        this.playManager.disabled = true
                    } else {
                        this.node.setPosition(x, targetY)
                        this.playManager.targetY = 0
                        this.playManager.targetX = 0
                        this.playManager.disabled = false
                        this.getNextLineList()
                        lv = new Vec2(0, 0);
                    }
                }
            }
        } else {
            this.status = ""
            this.playManager.state = PARAME_NAME_ENUM.IDLE
            if (this.initialize && !this.dizzy) {
                this.physicsTestAABB()
            }
        }
        rb!.linearVelocity = lv;
    }
}


